/**
 * Die Klasse Huffman wurde automatisch erstellt: 
 * 
 * @author Lars Götte, Erhan Günes
 * @version 30.9.2013
 */

import sum.komponenten.*;
import sum.werkzeuge.*;
import sum.ereignis.*;
import sum.strukturen.*;

public class Huffman extends EBAnwendung
{
    // Objekte
    private Etikett hatEtikettHuffmankompremierung;
    private Etikett hatEtikettAusgangstext;
    private Etikett hatEtikettZeichenhaeufigkeit;
    private Etikett hatEtikettHuffmanbaum;
    private Etikett hatEtikettHuffmancode;
    private Zeichenbereich hatQuelle;
    private Zeichenbereich hatZeichenbereich2;
    private Zeilenbereich hatZeilenbereichHaeufigkeit;
    private Zeilenbereich hatHuffmanbaum;
    private Knopf hatKnopfZaehlen;
    private Knopf hatKnopfCodieren;
    private Knopf hatKnopfBeenden;

    Liste<Baum> hatHuffmanliste;
    Textwerkzeug hatTW;

    // Attribute

    /**
     * Konstruktor
     */
    public Huffman()
    {
        //Initialisierung der Oberklasse
        super(775, 500);

        hatEtikettHuffmankompremierung = new Etikett(225, 50, 325, 25, "Huffman-Kompremierung");
        // Ausrichtung
        hatEtikettHuffmankompremierung.setzeAusrichtung(Ausrichtung.MITTE);
        hatEtikettAusgangstext = new Etikett(50, 100, 150, 25, "Ausgangstext");
        // Ausrichtung
        hatEtikettAusgangstext.setzeAusrichtung(Ausrichtung.MITTE);
        hatEtikettZeichenhaeufigkeit = new Etikett(225, 100, 150, 25, "Zeichenhäufigkeit");
        // Ausrichtung
        hatEtikettZeichenhaeufigkeit.setzeAusrichtung(Ausrichtung.MITTE);
        hatEtikettHuffmanbaum = new Etikett(400, 100, 150, 25, "Huffman-Baum");
        // Ausrichtung
        hatEtikettHuffmanbaum.setzeAusrichtung(Ausrichtung.MITTE);
        hatEtikettHuffmancode = new Etikett(575, 100, 150, 25, "Huffman-Code");
        // Ausrichtung
        hatEtikettHuffmancode.setzeAusrichtung(Ausrichtung.MITTE);
        hatQuelle = new Zeichenbereich(50, 150, 150, 200, "");
        hatZeichenbereich2 = new Zeichenbereich(575, 150, 150, 200, "");
        hatZeilenbereichHaeufigkeit = new Zeilenbereich(225, 150, 150, 200, "");
        hatHuffmanbaum = new Zeilenbereich(400, 150, 150, 200, "");
        hatHuffmanbaum.setzeSchriftart("Courier");
        hatKnopfZaehlen = new Knopf(225, 375, 150, 25, "Zählen");
        hatKnopfZaehlen.setzeBearbeiterGeklickt("hatKnopfZaehlenGeklickt");
        hatKnopfCodieren = new Knopf(400, 375, 150, 25, "Codieren");
        hatKnopfCodieren.setzeBearbeiterGeklickt("hatKnopfCodierenGeklickt");
        hatKnopfBeenden = new Knopf(312, 425, 150, 25, "Beenden");
        hatKnopfBeenden.setzeBearbeiterGeklickt("hatKnopfBeendenGeklickt");

        hatHuffmanliste = new Liste<Baum>();
        hatTW = new Textwerkzeug();
    }

    /**
     * Vorher: Ereignis GeklicktvonhatKnopfZaehlen fand statt.
     * Nachher: (schreiben Sie, was in dieser Methode ausgefuehrt wird)
     */
    public void hatKnopfZaehlenGeklickt()
    {
        String lQuelltext;
        char lChar;
        boolean lVorhanden;
        Baum lBaum;
        Zeichen lZeichen;

        hatHuffmanliste.entferneAlleElemente();
        lQuelltext = hatQuelle.inhaltAlsText();
        for(int i=1; i<= hatTW.laenge(lQuelltext); i++){
            lChar = hatTW.zeichenAn(lQuelltext, i);
            lVorhanden = false;
            hatHuffmanliste.zumAnfang();
            while(!hatHuffmanliste.istDahinter() && !lVorhanden){
                lBaum = (Baum)hatHuffmanliste.aktuellesElement();
                lZeichen = (Zeichen)lBaum.inhalt();
                if(lZeichen.zeichen() == lChar){
                    lVorhanden = true;
                    lZeichen.erhoeheAnzahl();
                }
                hatHuffmanliste.vor();
            }
            if(!lVorhanden){
                lZeichen = new Zeichen(lChar);
                lBaum = new Baum(lZeichen);
                hatHuffmanliste.fuegeDahinterEin(lBaum);
            }
            hatZeilenbereichHaeufigkeit.setzeInhalt(hatHuffmanliste.toString());
        }
    }

    /**
     * Vorher: Ereignis GeklicktvonhatKnopfCodieren fand statt.
     * Nachher: (schreiben Sie, was in dieser Methode ausgefuehrt wird)
     */
    public void hatKnopfCodierenGeklickt()
    {
        Baum lBaum1, lBaum2, lBaum3;
        int lPosition;
        Zeichen lZeichen1, lZeichen2, lZeichen3;

        while(hatHuffmanliste.laenge() > 1)
        {
            lBaum1 = this.kleinstesListenelement();
            lPosition = hatHuffmanliste.position(lBaum1);
            hatHuffmanliste.geheZuPosition(lPosition);
            hatHuffmanliste.loescheAktuelles();
            lBaum2 = this.kleinstesListenelement();
            lPosition = hatHuffmanliste.position(lBaum2);
            hatHuffmanliste.geheZuPosition(lPosition);
            hatHuffmanliste.loescheAktuelles();
            lZeichen1 = (Zeichen)lBaum1.inhalt();
            lZeichen2 = (Zeichen)lBaum2.inhalt();
            lZeichen3 = new Zeichen('#');
            lZeichen3.setzeAnzahl(lZeichen1.anzahl() + lZeichen2.anzahl());
            lBaum3 = new Baum(lZeichen3, lBaum1, lBaum2);
            hatHuffmanliste.zumEnde();
            hatHuffmanliste.fuegeDahinterEin(lBaum3);
        }
        hatHuffmanbaum.setzeInhalt(hatHuffmanliste.toString());
    }

    public Baum kleinstesListenelement()
    {
        Baum lListenelement, lBaumB;
        Zeichen lZeichenA, lZeichenB;
        int niedrigsteAnzahl;

        hatHuffmanliste.zumAnfang();                                
        lListenelement = (Baum)hatHuffmanliste.aktuellesElement();  
        lZeichenA = (Zeichen)lListenelement.inhalt();                       
        niedrigsteAnzahl = lZeichenA.anzahl();                   

        while (!hatHuffmanliste.istAmEnde())                   

        {
            hatHuffmanliste.vor();                             
            lBaumB = (Baum)hatHuffmanliste.aktuellesElement();
            lZeichenB = (Zeichen)lListenelement.inhalt();
            if (lZeichenB.anzahl() < niedrigsteAnzahl){   
                lListenelement = lBaumB;
            }
        }
        return lListenelement;
    }

    /**
     * Vorher: Ereignis GeklicktvonhatKnopfBeenden fand statt.
     * Nachher: (schreiben Sie, was in dieser Methode ausgefuehrt wird)
     */
    public void hatKnopfBeendenGeklickt()
    {
        this.beenden();
    }
}
